package com.hiabr.iep.common.web.monitor;

import com.alibaba.fastjson.JSON;
import com.hiabr.iep.common.domain.vo.resp.BaseResponse;
import com.hiabr.iep.common.utils.RequestUtil;
import com.hiabr.iep.common.utils.network.IpUtil;
import com.hiabr.iep.common.web.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 日志切面
 */
@Slf4j
@Component
@Aspect
public class LogAspect {

    //切入点
    @Pointcut("execution(public * com.hiabr.iep..controller..*.*(..))")
    public void pointcut() {

    }

    //前置通知
    @Before("pointcut()")
    public void Before(JoinPoint joinPoint) {
        HttpServletRequest request = RequestUtil.getHttpServletRequest();
        String ip = "";
        String url = "";
        String method = "";
        if (request != null) {
            ip = IpUtil.getIP(request);
            url = request.getRequestURI();
            method = request.getMethod();
        }
        Object[] args = joinPoint.getArgs();
        args = Arrays.stream(args).filter(o -> !(o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof MultipartFile)).toArray();
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        String[] parameterNames = signature.getParameterNames();
//        Map<String, Object> params = buildParams(parameterNames, args);
        log.info("[request]:\"{} {} {}\" {}", ip, method, url, JSON.toJSONString(args));
    }

    /**
     * 正常返回
     *
     * @param obj
     */
    @AfterReturning(pointcut = "pointcut()", returning = "obj")
    public void afterReturning(Object obj) {
        log.info("[response]:{}", JSON.toJSONString(obj));
    }

    /**
     * 异常返回
     *
     * @param e
     */
    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
    public void afterThrowing(Exception e) {
        String response = "";
        if (e instanceof BaseException) {
            BaseException baseException = (BaseException) e;
            response = JSON.toJSONString(BaseResponse.error(baseException.getCode(), e.getMessage()));
        } else {
            response = JSON.toJSONString(BaseResponse.error());
        }
        log.info("[response]:{}", response);
    }

    /**
     * 构建请求参数 key:value
     *
     * @param parameterNames
     * @param args
     * @return
     */
    private Map<String, Object> buildParams(String[] parameterNames, Object[] args) {
        Map<String, Object> params = new HashMap<>();
        for (int i = 0; i < parameterNames.length; i++) {
            String parameterName = parameterNames[i];
            Object parameterValue = args[i];
            //过滤request和response
            if (parameterValue instanceof HttpServletRequest || parameterValue instanceof HttpServletResponse) {
                continue;
            }
            //针对文件上传特殊处理
            if (parameterValue instanceof MultipartFile) {
                Map<String, Object> f = getFileParam((MultipartFile) parameterValue);
                params.put(parameterName, f);
                continue;
            }
            params.put(parameterName, parameterValue);
        }
        return params;
    }

    private Map<String, Object> getFileParam(MultipartFile file) {
        Map<String, Object> params = new HashMap<>();
        params.put("文件名", file.getOriginalFilename());
        params.put("文件类型", file.getContentType());
        params.put("文件大小", file.getSize());
        return params;
    }
}
